package game.graphics;

import static org.lwjgl.opengl.GL11.glCallList;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glTranslatef;

import java.io.Serializable;

import helpers.BlockTypeInfo;
import data.DataManager;
import data.DataManager.BlockType;

/**
 * Single block.
 * 
 * @author Tomas Zima
 */
public class Block implements Serializable
{
	/**
	 * Constructor.
	 */
	public Block()
	{
		blockType			= DataManager.BlockType.BLOCK_NONE;
		blockBackgroundType	= DataManager.BlockType.BACKGROUND_HEAVEN;
	}

	/**
	 * Constructor.
	 * It sets type of block, but not it's background.
	 * You shouldn't normally use this unless you know what you are doing!
	 * 
	 * @param blockType
	 */
	public Block(DataManager.BlockType blockType)
	{
		this();
		this.setBlockType(blockType);
	}
	
	/**
	 * Constructor.
	 * It sets type of block and it's background.
	 * 
	 * @param blockType
	 * @param blockBackgroundType
	 */
	public Block(DataManager.BlockType blockType, DataManager.BlockType blockBackgroundType)
	{
		this();
		this.setBlockType(blockType, blockBackgroundType);
	}
	
	/**
	 * Redraws object.
	 */
	public void redraw(int x, int y)
	{
		dataManager.rebindBlocks();
		
		glPushMatrix();
		glTranslatef(x, y, 0);
		
		if (this.blockType == BlockType.BLOCK_TREE_BOTTOM ||
			this.blockType == BlockType.BLOCK_TREE_BOTTOM_BREAK ||
			this.blockType == BlockType.BLOCK_TREE_LEAVES_LEFT ||
			this.blockType == BlockType.BLOCK_TREE_LEAVES_RIGHT ||
			this.blockType == BlockType.BLOCK_TREE_MIDDLE ||
			this.blockType == BlockType.BLOCK_TREE_MIDDLE_BREAK ||
			this.blockType == BlockType.BLOCK_TREE_MIDDLE_LEFT ||
			this.blockType == BlockType.BLOCK_TREE_MIDDLE_LEFT_BREAK ||
			this.blockType == BlockType.BLOCK_TREE_MIDDLE_RIGHT ||
			this.blockType == BlockType.BLOCK_TREE_MIDDLE_RIGHT_BREAK ||
			this.blockType == BlockType.BLOCK_TREETOP_BOTTOM_LEFT ||
			this.blockType == BlockType.BLOCK_TREETOP_BOTTOM_MIDDLE ||
			this.blockType == BlockType.BLOCK_TREETOP_BOTTOM_RIGHT ||
			this.blockType == BlockType.BLOCK_TREETOP_MIDDLE_LEFT ||
			this.blockType == BlockType.BLOCK_TREETOP_MIDDLE_MIDDLE ||
			this.blockType == BlockType.BLOCK_TREETOP_MIDDLE_RIGHT ||
			this.blockType == BlockType.BLOCK_TREETOP_TOP_LEFT ||
			this.blockType == BlockType.BLOCK_TREETOP_TOP_MIDDLE ||
			this.blockType == BlockType.BLOCK_TREETOP_TOP_RIGHT ||
			
			this.blockType == BlockType.BLOCK_SHROOM_BROWN ||
			this.blockType == BlockType.BLOCK_SHROOM_RED ||
			this.blockType == BlockType.BLOCK_SAMPLING || 
					
			
			this.blockType == BlockType.BLOCK_CACTUS ||
			this.blockType == BlockType.BLOCK_CACTUS_TOP ||
			this.blockType == BlockType.BLOCK_CACTUS_BREAK)
		{
			glCallList(dataManager.getDisplayListID(blockBackgroundType));
			glCallList(dataManager.getDisplayListID(blockType));
		}
		else
		{
			if (this.isExisting())
			{
				glCallList(dataManager.getDisplayListID(blockType));
			}
			else
			{
				glCallList(dataManager.getDisplayListID(blockBackgroundType));
			}
		}
		
		glPopMatrix();
	}
	
	/**
	 * Sets block type.
	 * 
	 * @param blockType
	 */
	public void setBlockType(DataManager.BlockType blockType)
	{
		this.blockType = blockType;
	}
	
	public void setBlockType(DataManager.BlockType blockType, DataManager.BlockType blockBackgroundType)
	{
		this.blockType				= blockType;
		this.blockBackgroundType	= blockBackgroundType;
	}
	
	/**
	 * Returns type of block.
	 * 
	 * @return
	 */
	public DataManager.BlockType getBlockType()
	{
		return blockType;
	}
	
	/**
	 * Returns type of background of block.
	 * 
	 * @return
	 */
	public DataManager.BlockType getBackgroundType()
	{
		return blockBackgroundType;
	}
	
	/**
	 * Checks if block actually exists or it is empty.
	 * 
	 * @return
	 */
	public boolean isExisting()
	{
		if (blockType == DataManager.BlockType.BLOCK_NONE)
		{
			return false;
		}
		else
		{
			return true;
		}
	}
	
	/**
	 * Returns basic block of this type.
	 * 
	 * @return
	 */
	public BlockType getBasicBlockType()
	{
		return BlockTypeInfo.getBasicType(blockType);
	}
	
	/**
	 * It will destroy block, so only background will be drawn.
	 */
	public void destroy()
	{
		state -= 25;
		
		if (state < 50)
		{
			this.blockType = BlockTypeInfo.getBrokenBlockType(blockType);
		}
	}
	
	// Type of block and it's environment
	private DataManager.BlockType	blockType;
	private DataManager.BlockType	blockBackgroundType;
	
	// State of the block in percents
	private int state = 100;
	
	// Instance of DataManager
	private final DataManager dataManager = DataManager.getInstance();
}
